﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace fes
{
    public class Ekstremum : IComparable
    {
        private DateTime _XTime;
        private double _XValue;

        public DateTime XTime { get { return _XTime; } set { _XTime = value; } }
        public double XValue { get { return _XValue; } set { _XValue = value; } }

        public Ekstremum(double extremumValue, DateTime extremumTime) 
        {
            _XTime = extremumTime;
            _XValue = extremumValue;
        }


        public static bool operator <(Ekstremum ng1, Ekstremum ng2)
        {

            return ng1.XValue < ng2.XValue;

        }

        public static bool operator >(Ekstremum ng1, Ekstremum ng2)
        {

            return ng1.XValue > ng2.XValue;

        }

        public static bool operator ==(Ekstremum ng1, Ekstremum ng2)
        {
            if (ng1.XValue == ng2.XValue) return true;
            return false;

        }

        public static bool operator !=(Ekstremum ng1, Ekstremum ng2)
        {

            if (ng1.XValue != ng2.XValue) return true;
            return false;

        }

        public int CompareTo(object obj)
        {
            Ekstremum u = (Ekstremum)obj;
            return this.XValue.CompareTo(u.XValue);
        }
    }
    
    public class Best
    {
        private List<Ekstremum> minimums = new List<Ekstremum>();
        private List<Ekstremum> maximums = new List<Ekstremum>();

        private double lastPrice=-1;
        private DateTime lastPriceTime;
        private double lastLastPrice = -1;
        private bool init = false;

        private Ekstremum _Buy;
        private Ekstremum _Sell;
        private double _Profit = 0.0;
        public Ekstremum Buy { get { return _Buy; } }
        public Ekstremum Sell { get { return _Sell; } }
        public double Profit { get { return _Profit; } }

        public Best() 
        {

        }

        public void PushNext(double Price, DateTime t )
        {
            if (lastLastPrice == -1){ lastLastPrice = Price; return;}
            if (lastPrice == -1) { lastPrice = Price; lastPriceTime = t; return; }

            //else
            if (lastPrice < Price)
            {
                if (lastLastPrice < lastPrice) 
                {
                    lastLastPrice = lastPrice;
                    lastPrice = Price;
                    lastPriceTime = t;
                }
                else if (lastLastPrice >= lastPrice) 
                {
                    minimums.Add(new Ekstremum(lastPrice, lastPriceTime));
                    lastLastPrice = lastPrice;
                    lastPrice = Price;
                    lastPriceTime = t;
                }
            }
            else if (lastPrice > Price)
            {
                if (lastLastPrice > lastPrice)
                {
                    lastLastPrice = lastPrice;
                    lastPrice = Price;
                    lastPriceTime = t;
                }
                else if (lastLastPrice <= lastPrice)
                {
                    maximums.Add(new Ekstremum(lastPrice, lastPriceTime));
                    lastLastPrice = lastPrice;
                    lastPrice = Price;
                    lastPriceTime = t;
                }

            }
            else { lastLastPrice = lastPrice; lastPrice = Price; lastPriceTime = t; }

            if(!init)
               if ((minimums.Count > 0) && (maximums.Count > 0)) init = true;
        }

        public void Clear()
        {
            maximums.Clear();
            minimums.Clear();
            init = false;
            lastPrice = -1;
            lastLastPrice = -1;
            _Buy = null;
            _Sell = null;
        }

        public void CalculateBest()
        {
            if (!init) return;

            minimums.Sort();
            maximums.Sort();

            Ekstremum min = minimums[0];
            Ekstremum max = maximums[0];
            double val=-1;

            for (int i = 0; i < minimums.Count; i++) 
            {
                for (int k = maximums.Count-1; k >= 0; k--) 
                {
                    if (maximums[k].XTime > minimums[i].XTime)
                    {
                       if((maximums[k].XValue - minimums[i].XValue) > val) 
                       {
                            val = (maximums[k].XValue - minimums[i].XValue);
                            min = minimums[i];
                            max = maximums[k];
                       } 
                       else break; //jump out the maximum loop, because there is no beter value;
                    }
                }
            
            }

            _Buy = min;
            _Sell = max;

            _Profit = (max.XValue - min.XValue) / min.XValue * 100.0;
        }

    }
}
